from django.shortcuts import render, redirect, reverse, HttpResponse
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json
import requests

from web.forms.file import FolderModelForm, FileModelForm
from web import models
from utils.tencent.tencent_cos import delete_file, delete_file_list, credential


def file(request, project_id):
    """显示文件和文件、添加文件"""
    # GET查看
    parent_project = None
    # folder_id有值就是在该文件夹下创建文件/文件夹
    # 没有值就是在根目录下创建
    folder_id = request.GET.get("folder", "")
    if folder_id.isdecimal():
        parent_project = models.FileRepository.objects.filter(id=int(folder_id), file_type=2,
                                                              project=request.tracer.project).first()
    if request.method == 'GET':
        # 面包屑导航
        breadcrumb = []
        parent = parent_project
        while parent:
            breadcrumb.insert(0, {"id": parent.id, "name": parent.name})
            parent = parent.parent

        # 查看文件夹/文件列表
        query_set = models.FileRepository.objects.filter(project=request.tracer.project)
        if parent_project:
            # 查看某目录下的文件/文件夹
            file_object_list = query_set.filter(parent=parent_project).order_by("-file_type")
        else:
            # 查看根目录
            file_object_list = query_set.filter(parent__isnull=True).order_by("-file_type")

        form = FolderModelForm(request, parent_project)
        context = {
            "form": form,
            "file_object_list": file_object_list,
            "breadcrumb": breadcrumb,
            "folder_object": parent_project
        }
        return render(request, "file.html", context)

    # POST 添加文件/修改文件夹
    fid = request.POST.get("fid", "")
    edit_object = None
    if fid.isdecimal():
        edit_object = models.FileRepository.objects.filter(id=int(fid), project=request.tracer.project.id).first()

    if edit_object:
        form = FolderModelForm(request, parent_project, data=request.POST, instance=edit_object)
    else:
        form = FolderModelForm(request, parent_project, data=request.POST)

    if form.is_valid():
        form.instance.project = request.tracer.project
        form.instance.file_type = 2
        form.instance.update_user = request.tracer.user
        form.instance.parent = parent_project
        form.save()

        return JsonResponse({"status": True})

    return JsonResponse({"status": True, "error": form.errors})


def file_delete(request, project_id):
    """删除文件"""
    fid = request.GET.get("fid")
    # 删除数据库中的文件/文件夹
    delete_object = models.FileRepository.objects.filter(id=fid, project=request.tracer.project).first()
    if delete_object.file_type == 1:
        # 删除文件
        request.tracer.project.use_space -= delete_object.file_size
        request.tracer.project.save()

        # cos删除文件
        delete_file(request.tracer.project.bucket, request.tracer.project.region, delete_object.key)

        delete_object.delete()
        return JsonResponse({"status": True})

    # 删除文件夹
    total_size = 0
    folder_list = [delete_object,]
    key_list = []
    for folder in folder_list:
        child_list = models.FileRepository.objects.filter(parent=folder, project=request.tracer.project).order_by("-file_type")
        for child in folder:
            if child.file_type == 2:
                folder_list.append(child)
            else:
                total_size += child.file_size
                key_list.append({"Key": child.key})

    if key_list:
        # cos批量删除文件
        delete_file(request.tracer.project.bucket, request.tracer.project.region, key_list)

    # 归还容量
    if total_size:
        request.tracer.project.use_space -= total_size
        request.tracer.project.save()

    delete_object.delete()
    return JsonResponse({"status": True})


@csrf_exempt
def cos_credential(request, project_id):
    # 单文件文件的字节大小
    per_file_size = request.tracer.price_policy.per_file_size * 1024 * 1024
    # 所有文件的总大小(已上传文件与新上传文件)
    total_file_size = request.tracer.price_policy.project_space * 1024 * 1024 * 1024

    # 获取cos临时凭证
    # 做文件大小限制：单文件大小，总文件大小
    file_list = json.loads(request.body.decode("utf-8"))
    total_size = 0
    for item in file_list:

        if item['size'] > per_file_size:
            msg = "单文件超出限制(最大{}M),文件：{} 超出限制，请升级套餐".format(request.tracer.price_policy.per_file_size, item["size"])
            return JsonResponse({"status": False, "error": msg})

        total_size += item['size']

    # 总容量限制
    # 单项目空间
    # request.tracer.price_policy.project_space
    # 已使用空间
    # request.tracer.project.use_space
    if request.tracer.project.use_space + total_size > total_file_size:
        return JsonResponse({"status": False, "err": "项目空间已不足，请升级套餐"})

    data_dict = credential(request.tracer.project.bucket, request.tracer.project.region)
    return JsonResponse({"status": True, "data": data_dict})


@csrf_exempt
def file_post(request, project_id):
    """已上传成功的文件写入数据库中"""
    # print(request.POST)
    # 把获取到的数据写入到数据库中

    """
        name: fileName,
        key: key,
        file_size: fileSize,
        parent: CURRENT_FOLDER_ID,
        etag: data.ETag,
        file_path: data.Location
    """
    # print(request.POST)
    # 把获取到的数据写入数据库即可
    form = FileModelForm(request, data=request.POST)
    if form.is_valid():
        # 校验通过，写入到数据库
        data_dict = form.cleaned_data
        data_dict.pop("etag")
        data_dict.update({"project": request.tracer.project, "file_type": 1, "update_user": request.tracer.user})

        # 项目已使用空间
        request.tracer.project.use_space += data_dict.get("file_size")
        request.tracer.project.save()

        instance = models.FileRepository.objects.create(**data_dict)
        result = {
            "id": instance.id,
            "name": instance.name,
            "file_size": instance.file_size,
            "username": instance.update_user.username,
            "download_url": reverse("file_download", kwargs={"project_id": request.tracer.project.id, "file_id": instance.id}),
            'datetime': instance.update_time.strftime('%Y{y}%m{m}%d{d} %H{h}%M{f}%S{s}').format(y='年', m='月', d='日', h='时', f='分', s='秒'),
        }

        return JsonResponse({"status": True, "data": result})

    return JsonResponse({"status": False, "data": "文件错误"})


def file_download(request, project_id, file_id):
    """文件下载"""
    file_obj = models.FileRepository.objects.filter(id=file_id, project=request.tracer.project).first()
    res = requests.get(file_obj.file_path)
    # 文件分块处理
    data = res.iter_content()

    # 设置content_type="application/octet-strem" 用于提示下载框
    response = HttpResponse(data, content_type="application/octet-strem")
    from django.utils.encoding import escape_uri_path

    # 设置响应头：中文文件名转义
    response["Content-Disposition"] = "attachment; filename={}".format(escape_uri_path(file_obj.name))
    return response

